#!/bin/bash
#############################################
# author:fang
# version : v1.0
# name  : xjava
# dispcripe: java operators
# CopyRight@fangyunjiang[42550564@qq.com]
#############################################
source ~/command/common

_full_class_name=""
_jarfile=""
_path=""
_header=""
_android=0
_jni=0
_oper=0
_build=0
_check=0
android_skd_jar=~/android/android-sdk-macosx/platforms/android-10/android.jar
classpath_file=~/.java_classpath
header_file=~/.java_header
sep=":"
if __windows;then
	sep=";"
fi
m2_jar=(`cat ${classpath_file} 2>/dev/null`)
m2_classpath=".${sep}moment-1.0.0.jar${sep}underscore-1.45.jar"
for x in "${m2_jar[@]}";do
	m2_classpath="${m2_classpath}${sep}${x}"
done

function xjavaGetPackage()
{
	local class_name package
	class_name="$1"
	package="${_full_class_name%$class_name}"
	echo "${package%.}"
}

function xjavaGetPackageFromFile()
{
	local file_name
	file_name="$1"
	echo "$(sed -n '/package.*\;/p' $file_name|sed 's/package//;s/;//;s/[[:space:]]//')"
}

function xjavaGetJniFlag()
{
	local file_name ret
	file_name="$1"
	ret=$(sed -n '/native.*();/p' $file_name)
	[ -z "$ret" ]&&_jni=0||_jni=1
}

function xjavaGetFileName()
{
	local class_name file_name package
	package="$1"
	class_name="$2"
	if [ -n "$package" ];then
		mkdir -p "src/${package//.//}"
		file_name="src/${package//.//}/$class_name.java"
	else
		file_name="src/$class_name.java"
	fi
	echo "$file_name"
}

function xjavaCreateClass()
{
	local class_name file_name package

	class_name=${_full_class_name##*.}
	package=$(xjavaGetPackage "$class_name")
	file_name=$(xjavaGetFileName "$package" "$class_name")

	if [ -z "${class_name}" ];then
		echo "请输入类名"
		exit
	fi

	mkdir -p src
	__backup_file "$file_name"

	[ -n "$package" ] && echo "package $package;" >> $file_name
		echo "">> $file_name
		echo "">> $file_name
		echo "public class $class_name {" >> $file_name
		echo "">> $file_name
	if [ $_jni -eq 1 ];then
		echo "	public native void func();" >> $file_name
		echo "">> $file_name
		echo "	static {" >> $file_name
		echo "		System.loadLibrary(\""$class_name"jni\");" >> $file_name
		echo "	}" >> $file_name
		echo "">> $file_name
		echo "">> $file_name
	fi
	echo "	public static void main(String[] args) {">> $file_name
	echo "		$class_name _$class_name = new $class_name(); ">> $file_name
	echo "		System.out.println(\"hello world\");" >> $file_name
	if [ $_jni -eq 1 ];then
		echo "		_$class_name.func();" >> $file_name
	fi
	echo "	}" >> $file_name
	echo "}" >> $file_name
}

function xjavaCompileJava()
{
	local class_name package file_name cpackage

	class_name=${_full_class_name##*.}
	package=$(xjavaGetPackage "$class_name")
	file_name=$(xjavaGetFileName "$package" "$class_name")

	if [ $_check -eq 1 ];then
		cpackage=$(xjavaGetPackageFromFile $file_name)
		[ "$package" = "$cpackage" ] ||  __error "check package error!"
	fi

	mkdir -p  bin/classes

	if [ $_android -eq 0 ];then
		javac -d bin/classes $file_name -classpath ${m2_classpath} || return $_FALSE_
	else
		javac -d bin/classes -bootclasspath $android_skd_jar $file_name || return $_FALSE_
	fi

	xjavaGetJniFlag "$file_name"
	if [ $_jni -eq 1 -a -f "jni/$class_name"jni.c ];then
		mkdir -p libs
		gcc -g -dynamiclib -undefined suppress -flat_namespace jni/"$class_name"jni.c -o libs/lib"$class_name"jni.dylib -I/System/Library/Frameworks/JavaVM.framework/Headers||return $_FALSE_
		echo gcc -dynamiclib -undefined suppress -flat_namespace jni/"$class_name"jni.c -o libs/lib"$class_name"jni.dylib -I/System/Library/Frameworks/JavaVM.framework/Headers
	fi

	return $_TRUE_
}

function xjavaExecuteJar()
{
	local class_name yy

	tar xvf $_jarfile META-INF/MANIFEST.MF 1>/dev/null 2>&1
	class_name=$(__get_line "Main-Class:" META-INF/MANIFEST.MF)
	class_name=${class_name##Main-Class: }
	class_name=$(echo $class_name|tr -d [:cntrl:])
	$_RM_ -fr META-INF

	tar xvf $_jarfile libs 1>/dev/null 2>&1
	java -cp $_jarfile -Djava.library.path=libs $class_name
	$_RM_ -fr libs 1>/dev/null 2>&1
}

function xjavaExecute()
{
	if [ $_build -eq 1 ];then
		xjavaCompileJava
	fi
	if [ $_android -eq 0 ];then
		java -cp bin/classes${sep}${m2_classpath} -Djava.library.path=libs $_full_class_name
	else
		echo "not complete!"
	fi
}

function xjavaCompressionJar()
{
	local author class_name list

	class_name=${_full_class_name##*.}
	author="fangyunjiang" #${LOGNAME}

	xjavaCompileJava || return $_FALSE_

	echo "compile java to class complete ... "

	cp -r bin/classes _jar_
	cd _jar_
	[ -d ../libs ] && cp -r ../libs libs

	echo "Manifest-Version: 1.0" > manifest.mf
	echo "Created-By: $author" >> manifest.mf
	echo "Class-Path: classes" >> manifest.mf
	echo "Main-Class: $_full_class_name" >> manifest.mf
	echo "create manifest.mf complete ... "

  	list=`ls`
    list=${list/manifest.mf/}
    list="manifest.mf $list"
    jar cvfm $class_name.jar $list
	echo "create jar file complete ..."
	mv $class_name.jar ..
	cd ..
	$_RM_ -fr _jar_
}

function xjavaCreateJniNativeFile()
{
	local class_name package file_name head_file src_file

	class_name=${_full_class_name##*.}
	package=$(xjavaGetPackage "$class_name")
	file_name=$(xjavaGetFileName "$package" "$class_name")

	xjavaGetJniFlag "$file_name"
	[ $_jni -eq 0 ]&&return

	head_file=jni/$class_name"jni.h"
	src_file=jni/$class_name"jni.c"

	mkdir -p jni
	mkdir -p  bin/classes

	javah -classpath bin/classes -o $head_file -jni $_full_class_name||return $_FALSE_

	__backup_file "$src_file"
	echo "#include <stdio.h>" > $src_file
	echo "#include \""$class_name"jni.h\"" >> $src_file
	echo  >> $src_file
	sed -n '/JNIEXPORT/,/);/p' $head_file|sed 'N;s/\n//'|sed 's/  (/(/;s/;/{\n\tprintf("hello jni\\n");\n}/;s/JNIEnv \*/JNIEnv *env/;s/jobject/jobject obj/;s/jclass/jclass cls/' >> $src_file
	echo  >> $src_file
	return $_TRUE_
}

function addClassPath() {
	if [ -a "$_path" ];then
		_path=$(__get_full_path "$_path")
		if ! [ -z "$_path" ];then
			echo "$_path" >> ${classpath_file}
		fi
	else
		echo "current class path in ${classpath_file}:"
		cat ${classpath_file} 2>/dev/null
	fi
}

function addCommonHeader() {
	if [ -n "$_header" ];then
		echo "${_header%%;*};" >> ${header_file}
	else
		cat ${header_file} 2>/dev/null
	fi
}

function runCodeForXJ() {
	cd $HOME/command/java
	javac Test.java -classpath "${m2_classpath}" -Xlint:unchecked
	if [ $? -ne 0 ];then
		return
	fi
	java -cp "${m2_classpath}" Test
}

function xjavaShowHelp()
{
	local -a list

	list="help"
	list=("${list[@]}" "Usage: xjava [-n full_class_name|-c|-b|-e|-r|-p|-f|-a|-j|-h]")
	list=("${list[@]}" "-n full_class_name: set full_class_name[package.Class]")
	list=("${list[@]}" "-c: create class")
	list=("${list[@]}" "-b: build/complie java project")
	list=("${list[@]}" "-e: execute program")
	list=("${list[@]}" "-r jarfile: execute program with jarfile")
	list=("${list[@]}" "-p: compress jar file")
	list=("${list[@]}" "-f: create jni header file and src file")
	list=("${list[@]}" "-a: package with android")
	list=("${list[@]}" "-j: has native jni functions,only with -c")
	list=("${list[@]}" "-d path: add classpath, if path is null, show classpath")
	list=("${list[@]}" "-k package: add common header, if path is null, show headers")
	list=("${list[@]}" "-s: compile and execute for xj")
	list=("${list[@]}" "-h: show help")
	list=("${list[@]}" "")
	list=("${list[@]}" "without jni:")
	list=("${list[@]}" "xjava -n com.xx.name -c")
	list=("${list[@]}" "xjava -n com.xx.name -b")
	list=("${list[@]}" "xjava -n com.xx.name -e")
	list=("${list[@]}" "")
	list=("${list[@]}" "with jni:")
	list=("${list[@]}" "xjava -n com.xx.name -c -j")
	list=("${list[@]}" "xjava -n com.xx.name -b")
	list=("${list[@]}" "xjava -n com.xx.name -f")
	list=("${list[@]}" "xjava -n com.xx.name -b")
	list=("${list[@]}" "xjava -n com.xx.name -e")
	list=("${list[@]}" "")
	list=("${list[@]}" "Author:fangyunjiang")
	list=("${list[@]}" "Version:V1.0")

	__msgbox "${list[@]}"
}

function main()
{
	while getopts :n:cber:d:k:pfajsh opt;do
		case $opt in
			n)_full_class_name="$OPTARG";;
			c)_oper=0;;
			b)_oper=1;_build=1;;
			e)_oper=2;;
			r)_oper=3;_jarfile="$OPTARG";;
			p)_oper=4;;
			f)_oper=5;;
			a)_android=1;;
			j)_jni=1;;
			d)_oper=6;_path="$OPTARG";;
			k)_oper=7;_header="$OPTARG";;
			s)_oper=8;;
			h)xjavaShowHelp;exit;;
			?)xjavaShowHelp;exit;;
		esac
	done

	case $_oper in
		0)xjavaCreateClass;;
		1)xjavaCompileJava;;
		2)xjavaExecute;;
		3)xjavaExecuteJar;;
		4)xjavaCompressionJar;;
		5)xjavaCreateJniNativeFile;;
		6)addClassPath;;
		7)addCommonHeader;;
		8)runCodeForXJ;;
	esac
}

main "$@"
